import path from "path";
import fs from "fs";
import { exit } from 'process';

import sugar from '../core/sugar'
import errorCatch from '../entrance/event/errorCatch';
// 引入控制路由结构的方法
import controRoute from './RouterHandler';
import ConfigHandler from '../init/ConfigHandler';
import Middleware from '../middleware/middleware';
import RequestType from '../model/RequestType';

export = Router;
class Router {
  private static KEY = 0;
  /** 路由队列 */
  public static routerMap = new Map();
  
  // 唯一身份ID
  private id: any = undefined;
  /** 未处理的静态路由 */
  private unStaticRoute = new RequestType();
  /** 未处理的动态路由 */
  private unDynamicRoute = new RequestType();
  // 文件信息
  private RouteData: {
    middleware: Array<any>,
    prefix: string
  } = {
      middleware: [],
      prefix: "",
    };

  static midd(arr: Array<any>, arr2: Array<any>) { arr.push(...arr2, arr.pop()) }

  // 构造方法,统一命名空间
  constructor(id: any = undefined, key?: any) {
    this.id = key || Router.KEY++
    try {
      if (!id) { id = sugar.super_path(2, true); console.log("构造参数为空,建议添加 __filename") }
      if (typeof id === 'string') {
        //获取配置中的路由文件配置
        let config:Array<routeFile>= ConfigHandler.getRouteConfig();
        //遍历
        let status = config.some((e:routeFile):boolean=>{
            let filepath = sugar.path(e.path);
            if (path.join(filepath).startsWith(path.join(id))) {
              if (!this.id) {
                this.id = path.join(id);
              }
              //吻合了,自动加载配置
              this.RouteData = {
                //前缀
                prefix: e.prefix === '/' ? "" : e.prefix,
                //中间件  
                middleware: controRoute.getGlobalMiddleware().concat(e.middleware),
              };
              // 初始化一下数据
              controRoute.addUnStaticRoute(this.id, this.unStaticRoute);
              controRoute.addUnDynamicRoute(this.id, this.unDynamicRoute);
              return true;
            }
            return false;
        })
        if(!status){
          //遍历完也没有找到配置,直接报错
          console.log("报异常");
          throw new Error("并未在配置文件中找到该路由的配置,请检查配置文件");
          exit();
        }
      } else if (typeof id === 'object') {
        this.id = path.join(id.id);
        //执行到这里,说明发来的是配置信息
        this.RouteData = {
          prefix: id.prefix === '/' ? "" : id.prefix || "",
          middleware: ConfigHandler.getGlobal_Middleware().concat(id.middleware || [])
        }
      }
      // 初始化一下数据
      controRoute.addUnStaticRoute(this.id, this.unStaticRoute);
      controRoute.addUnDynamicRoute(this.id, this.unDynamicRoute);
    } catch (err) {
      errorCatch(err, "Route-71")
    }
  }

  // 重新配置这个路由实列的信息
  config(data: any) {
    this.RouteData = {
      prefix: data.prefix === '/' ? "" : data.prefix,
      middleware: ConfigHandler.getGlobal_Middleware().concat(data.middleware)
    }
  }

  // 特殊接口的配置
  private special(name: string, module: any) {
    controRoute.addSpecialRoute(name, {
      modules: [],
      controller: Router.createController(name, module, name)
    });
    return { midd: (...data) => { Router.midd(controRoute.getSpecialRoute(name).modules as Array<any>, data) } }
  }
  private createSpecial(name: string): Function {
    return (module: any) => {
      this.special(name, module);
    }
  }

  // 特殊接口
  public $500 = this.createSpecial("500")
  public $404 = this.createSpecial("404")
  public $public = this.createSpecial("public")
  public $requestRecord = this.createSpecial("requestRecord")
  public $requestParse = this.createSpecial("requestParse")

  //执行分组
  public group({ prefix = "", midd = [] }: { prefix: string, midd: any }, fun: Function) {
    try {
      let middleware = this.RouteData.middleware;
      let _prefix = this.RouteData.prefix;
      //解析出来的组级中间件是一个Promise
      this.RouteData.middleware = this.RouteData.middleware.concat(midd);
      this.RouteData.prefix += prefix.startsWith("/") ? prefix : "/" + prefix;
      fun();
      this.RouteData.middleware = middleware;
      this.RouteData.prefix = _prefix;
    } catch (err) {
      errorCatch(err, 'Route:82');
    }
  }
  private createMethod(method: string) {
    return (url: string, fun: any, methodName?: string) => {
      if (url === undefined) throw new Error("url is null");
      return this.createRouteInter(method, url, Router.createController(url, fun, methodName));
    }
  }
  //any请求
  any = this.createMethod("any");
  // get请求
  get = this.createMethod("get");
  // post请求
  post = this.createMethod("post");
  // delete请求
  delete = this.createMethod("delete");
  // put请求
  put = this.createMethod("put");


  //创建路由接口
  private createRouteInter(type: string, url: string, controller: controllerStructure): middObject {
    if (!type || !url || !controller) throw new Error("参数错误")

    //处理url
    url.startsWith("/") || (url = "/" + url);
    //生成完整的url
    url = this.RouteData.prefix + url;
    //处理url
    url.startsWith("/") || (url = "/" + url);

    // 解析中间件
    let MiddlewareArr: Array<controllerStructure> = Middleware.auto_pars(this.id, this.RouteData.middleware);

    //判断是否是有路由参数的路由
    if (Router.isParameter(url)) {
      // 生成正则
      let andRout = Router.createRouteRegular(url);
      controller.parameter = andRout.parameter;

      //这是一个路由参数，生成正则表达式
      controRoute.addUnDynamicRouteInter(this.id, type, url, {
        // 基本信息
        data: { id: this.id, type, url, ...andRout },
        // 中间件模块
        modules: MiddlewareArr,
        // 控制器模块
        controller: controller
      })
      return {
        _super: this,
        midd(...data: any[]): void {
          let route = this._super.unDynamicRoute[type][url];
          route.modules.push(...Middleware.auto_pars(this._super.id, data))
        }
      }
    } else {
      this.unStaticRoute[type][url] = {
        data: { id: this.id, type, url },
        modules: MiddlewareArr,
        controller: controller
      }
    }

    //调用中间件
    return {
      _super: this,
      midd(...data: any[]): void {
        let route = this._super.unStaticRoute[type][url];
        route.modules.push(...Middleware.auto_pars(this._super.id, data))
      }
    }
  }


  //判断是否带有路由参数
  private static isParameter(str: string): any {
    return /\/:[^/]*/g.test(str);
  }

  //创建路由正则 
  private static createRouteRegular(str: any): dynamicRouteRegular {
    let parameter = str.match(/\/:[^/]*/g).map((a: string) => a.substring(2));
    //替换字
    let replace = str.split(/\/:[^/]*/g).filter((res: string) => res);
    //转换关键字
    str = str.replace(/\//g, "<_GEM_>");
    //生成正则表达式
    let regular = new RegExp("^" + str.replace(/(:((?!<_GEM_>).)+)/g, `((?!<_GEM_>).)+`) + "$");

    return {
      parameter,
      replace,
      regular
    }
  }

  //解析方法 创建控制器
  private static createController(id: string, module: any, name?: string): controllerStructure {
    if (typeof module === 'string') {
      // 不是绝对路径或相对路径的话，哪就是语法糖
      let [filePath, methodName] = module.split("@");
      // 判断是否是以项目或控制器为基路径
      if (!/^[./\\]|^[A-Z]\:/.test(module)) {
        let controllerPath = ConfigHandler.getAddress("controller")+"/"+filePath+".js";
        if(fs.existsSync(sugar.path(controllerPath))){
          filePath = controllerPath;
        }else{
          filePath=sugar.path(filePath+".js")
        }
        return Middleware.pars_string_middleware(filePath, methodName || name || "main", [])
      } else {
        // 解析路径
        filePath = sugar.path(filePath, { superNumber: 4 });
        return Middleware.pars_string_middleware(filePath, methodName || name || "main", []);
      }
    } else {
      return Middleware.auto_pars(id, module, name);
    }
  }

  /** 创建路由 */
  static createRoute(id: any) { return new Router(sugar.super_path(2, true), id) }
}